//=============================================================================
// DirectInput.cpp by Frank Luna (C) 2005 All Rights Reserved.
// Converted  to Singleton and debugged by Bart Uyttenhove
//=============================================================================
#include "stdafx.h"
#include "DirectInput.h"
#include "DXDevice.h"
#include "GameEngine.h"

DirectInput* DirectInput::m_pDirectInput = 0;
/**
* Singleton instance call
*/
DirectInput* DirectInput::GetSingleton()
{
	if(!m_pDirectInput)m_pDirectInput = new DirectInput();
	return m_pDirectInput;
}
/**
* Constructor creates keyboard and mouse device
*/
DirectInput::DirectInput():
	KeyboardCoopFlags(DISCL_NONEXCLUSIVE|DISCL_FOREGROUND), 
	MouseCoopFlags(DISCL_NONEXCLUSIVE|DISCL_FOREGROUND),
	m_pDInput(0),m_pKeyboard(0),m_pMouse(0)
{
	ZeroMemory(m_KeyboardState, sizeof(m_KeyboardState));
	ZeroMemory(&m_MouseState, sizeof(m_MouseState));

	HR(DirectInput8Create(GAME_ENGINE->GetInstance(), DIRECTINPUT_VERSION, 
		IID_IDirectInput8, (void**)&m_pDInput, 0));

	HR(m_pDInput->CreateDevice(GUID_SysKeyboard, &m_pKeyboard, 0));
	HR(m_pKeyboard->SetDataFormat(&c_dfDIKeyboard));
	HR(m_pKeyboard->SetCooperativeLevel(GAME_ENGINE->GetWindow(), KeyboardCoopFlags));
	HR(m_pKeyboard->Acquire());

	HR(m_pDInput->CreateDevice(GUID_SysMouse, &m_pMouse, 0));
	HR(m_pMouse->SetDataFormat(&c_dfDIMouse2));
	HR(m_pMouse->SetCooperativeLevel(GAME_ENGINE->GetWindow(), MouseCoopFlags));
	HR(m_pMouse->Acquire());
}

/**
* Destructor releases all comm resources and deletes all objects
*/
DirectInput::~DirectInput()
{
	m_pDInput->Release();
	m_pKeyboard->Unacquire();
	m_pMouse->Unacquire();
	m_pKeyboard->Release();
	m_pMouse->Release();
}
/**
* Get state of and retrieve data from keyboard and mouse
*/
void DirectInput::Poll()
{
	// Poll keyboard.
	HRESULT hr = m_pKeyboard->GetDeviceState(sizeof(m_KeyboardState), (void**)&m_KeyboardState); 
	if( FAILED(hr) )
	{
		// Keyboard lost, zero out keyboard data structure.
		ZeroMemory(m_KeyboardState, sizeof(m_KeyboardState));

		 // Try to acquire for next time we poll.
		hr = m_pKeyboard->Acquire();
		if(hr!=DI_OK)ShowError(hr);
	}

	// Poll mouse.
	hr = m_pMouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void**)&m_MouseState); 
	if( FAILED(hr) )
	{
		// Mouse lost, zero out mouse data structure.
		ZeroMemory(&m_MouseState, sizeof(m_MouseState));

		// Try to acquire for next time we poll.
		hr = m_pMouse->Acquire(); 
		if(hr!=DI_OK)ShowError(hr);
	}
}
void DirectInput::ShowError(HRESULT hr)
{
	tstringstream str;
	str<<_T("Error Aquire DirectInput Device: \n");
	switch(hr)
	{
	case DIERR_INVALIDPARAM:
		str << _T("DI ERR_INVALID PARAM.\n");
		break;
	case DIERR_NOTINITIALIZED:
		str << _T("DI ERR_NOT INITIALIZED.\n");
		break;
	case DIERR_OTHERAPPHASPRIO:
		str << _T("DI ERR_OTHER APP HAS PRIORITY.\n");
		break;
	}
	OutputDebugString(str.str().c_str());
}
/**
* Check if a key was down during last Poll call (first call Poll)
*/
bool DirectInput::KeyDown(unsigned char key)
{
	return (m_KeyboardState[key] & 0x80) != 0;
}

/**
* Check if a mousebutton was down during last Poll call (first call Poll)
*/
bool DirectInput::MouseButtonDown(int button)
{
	return (m_MouseState.rgbButtons[button] & 0x80) != 0;
}

/**
* Check mouse movement on X axis during last Poll call (first call Poll)
*/
float DirectInput::GetMouseDX() const
{
	return (float)m_MouseState.lX;
}

/**
* Check mouse movement on X axis during last Poll call (first call Poll)
*/
float DirectInput::GetMouseDY() const
{
	return (float)m_MouseState.lY;
}

/**
* Check mouse movement on X axis during last Poll call (first call Poll)
*/
float DirectInput::GetMouseDZ() const
{
	return (float)m_MouseState.lZ;
}